/* 
   Cifs Password Scanner
   Copyright (C) Patrik Karlsson 2004
   
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

package cqure;

import cqure.*;
import java.util.*;
import java.io.*;
import java.net.MalformedURLException;
import jcifs.smb.*;

public class CifsGuesser {

    private Vector m_oPasswords = null;
    private String m_sUser = "";
    private String m_sHost = "";
    private String m_sDomain = "";
    private String m_sFile = "IPC$";
    private AccountList m_oAccountList = null;
    private Logger m_oLogger = null;

    public CifsGuesser() {

    }

    /* Dirty hack */
    private String encode(String s) {
	return s.replaceAll("%", "%25").replaceAll("@", "%40");
    }


    public void setPasswords( Vector oP ) { m_oPasswords = oP; }
    public void setUser( String sUser ) { m_sUser = sUser; }
    public void setHost( String sHost ) { m_sHost = sHost; }
    public void setAccountList( AccountList o ) { m_oAccountList = o; }
    public void setLogger( Logger oLogger ) { m_oLogger = oLogger; }
    public void setDomain( String sDom ) { m_sDomain = sDom + ";"; }
    public void setShare( String sFile ) { m_sFile = sFile; }


    /*
     * For future reporting engine this might prove usefull
     * 
     */
    public void addAccount( String sUser, String sPass, 
			    String sHost, String sDomain, int nState ) {

	Account oA = new Account(sUser, sPass, sHost, sDomain, nState);
	m_oAccountList.add( oA );
	
    }
    

    public void guessPasswords() {

	String sPass = "";
	String sURL = "";
	SmbFile oF = null;

	for ( int i=0; i<m_oPasswords.size(); i++ ) {

	    sPass = (String) m_oPasswords.get( i );
	
	    if ( sPass.equalsIgnoreCase( "%username%" ) )
		sPass = m_sUser;
	    else if ( sPass.equalsIgnoreCase("lc %username%") )
		sPass = m_sUser.toLowerCase();

	    m_oLogger.debug("[-] Trying " + m_sUser + "/" + sPass + " ...");

	    try {
		sURL = "smb://" + encode(m_sDomain) + encode(m_sUser) + ":" +
		    encode(sPass) + "@" +m_sHost+"/" + m_sFile + "/";

		oF = new SmbFile( sURL );
	    }
	    catch( MalformedURLException e ) {
		m_oLogger.log("[x] The SMB/CIFS url is incorrect");
		return;
	    }

	    try {
		oF.connect();

		m_oLogger.log("[-] Account " + m_sUser + "/" +
			      sPass + " found");
			
		addAccount( m_sUser, sPass, m_sHost, m_sDomain,
			    SmbException.NT_STATUS_OK );

		return;

	    }
	    catch( SmbException e ) {

		switch( ((SmbException)e).getNtStatus() ) {
		case 0xC000000D:
		    m_oLogger.log("[-] Account " + m_sUser + "/" +
				  sPass + " found");
		    addAccount( m_sUser, sPass, m_sHost, m_sDomain,
				((SmbException)e).getNtStatus() );
		    return;
		case SmbException.NT_STATUS_OK:
		    m_oLogger.log("[-] Account " + m_sUser + "/" +
				  sPass + " found");
		    addAccount( m_sUser, sPass, m_sHost, m_sDomain,
				((SmbException)e).getNtStatus() );
		    return;
		case SmbException.NT_STATUS_ACCESS_DENIED:
		    break;
		case SmbException.NT_STATUS_WRONG_PASSWORD:
		    break;
		case SmbException.NT_STATUS_LOGON_FAILURE:
		    break;
		case SmbException.NT_STATUS_ACCOUNT_RESTRICTION:
		    m_oLogger.log("[-] Account " + m_sUser + "/" +
				  sPass + " is restricted");
		    addAccount( m_sUser, sPass, m_sHost, m_sDomain,
				((SmbException)e).getNtStatus() );
		    return;
		case SmbException.NT_STATUS_INVALID_LOGON_HOURS:
		    m_oLogger.log("[-] Account " + m_sUser + "/" +
				  sPass + " has logon hours restrictions");
		    addAccount( m_sUser, sPass, m_sHost, m_sDomain,
				((SmbException)e).getNtStatus() );
		    return;
		case SmbException.NT_STATUS_INVALID_WORKSTATION:
		    m_oLogger.log("[-] Account " + m_sUser + "/" +
				  sPass + " has workstation restrictions");
		    addAccount( m_sUser, sPass, m_sHost, m_sDomain,
				((SmbException)e).getNtStatus() );
		    return;
		case SmbException.NT_STATUS_PASSWORD_EXPIRED:
		    m_oLogger.log("[-] Account " + m_sUser + "/" +
				  sPass + " has expired");
		    addAccount( m_sUser, sPass, m_sHost, m_sDomain,
				((SmbException)e).getNtStatus() );
		    return;
		case SmbException.NT_STATUS_ACCOUNT_DISABLED:
		    m_oLogger.log("[-] Account " + m_sUser + "/" +
				  sPass + " is disabled");
		    addAccount( m_sUser, sPass, m_sHost, m_sDomain,
				((SmbException)e).getNtStatus() );
		    return;
		case SmbException.NT_STATUS_ACCOUNT_LOCKED_OUT:
		    m_oLogger.log("[-] Account " + m_sUser + "/" +
				  sPass + " is disabled");
		    addAccount( m_sUser, sPass, m_sHost, m_sDomain,
				((SmbException)e).getNtStatus() );
		    return;
		case 0xC0000224:
		    m_oLogger.log("[-] Account " + m_sUser + "/" +
				  sPass + 
				  " must change password on next logon");
		    addAccount( m_sUser, sPass, m_sHost, m_sDomain,
				((SmbException)e).getNtStatus() );
		    return;
		case SmbException.NT_STATUS_UNSUCCESSFUL:
		    if ( e.getRootCause() instanceof IOException )
			m_oLogger.log("[x] " + e.getMessage() );
		    return;


		}
	    }
	    /* Dummy */
	    catch( IOException e ) {

	    }
		
	}
    }


}
